<template>
	<view class="html-gender">
		<view class="uni-container">
			<uni-forms ref="form" :value="requiestForm" validateTrigger="bind">
				<uni-forms-item name="url" label="url" required><uni-easyinput v-model="requiestForm.url" /></uni-forms-item>
				<uni-forms-item name="request_data" label="请求参数"><vue-json-editor v-model="jsonStr" :mode="'code'" lang="zh"></vue-json-editor></uni-forms-item>
				<uni-forms-item name="request_methce" label="请求方式">
					<el-select size="small" style="max-width: 250rpx;" v-model="requiestForm.request_methce" value-key="name" placeholder="请选择">
						<el-option v-for="(item, index) in requistList" :key="index" :label="item" :value="item"></el-option>
					</el-select>
				</uni-forms-item>

				<view class="uni-button-group">
					<button type="primary" class="uni-button" style="width: 100px;" @click="submit">提交</button>
					<navigator open-type="navigateBack" style="margin-left: 15px;"><button class="uni-button" style="width: 100px;">返回</button></navigator>
				</view>
			</uni-forms>
		</view>
		<open-alert ref="openAlert" :AlertClass="1">
			<uni-forms ref="form2">
				<el-card class="box-card">
					<div slot="header" class="clearfix">
						<span>数据映射设置</span>
						<view>
							<el-button type="primary" :disabled="isCangender" size="small" @click="gengderJson">{{ generateBtn }}</el-button>
							<el-button type="info" size="small" :disabled="!isGenerate" @click="copyJson">复制json</el-button>
							<el-button type="success" size="small" :disabled="!isGenerate">
								<template v-if="!isGenerate">
									下载
								</template>
								<template v-else>
									<a class="down_btn" :href="'data:text/json;charset=utf-8,' + JSON.stringify(dataJson)" download="data.txt">下载数据</a>
								</template>
							</el-button>
							<el-button type="warning" size="small" :disabled="!isGenerate" @click="addTo">批量加入</el-button>
						</view>
					</div>
					<!-- 表单信息 -->
					<view class="cell_one" v-for="(item, index) in formItemList" :key="index">
						<uni-forms-item :name="'mapping_field_' + index" label="映射字段" :required="item.required">
							<el-tooltip effect="dark" content="从响应数据中选择需要的字段仅数组类型哦~" placement="top"><i class="info_desc el-icon-question"></i></el-tooltip>
							<el-cascader v-model="formItemList[index]['mapping_field']" placeholder="请选择要映射的字段" clearable :options="options" filterable></el-cascader>
						</uni-forms-item>
						<uni-forms-item :name="'mapped_to_' + index" label="映射到" :required="item.required">
							<el-tooltip effect="dark" content="映射到新json中的哪个字段. 如obj.name" placement="top"><i class="info_desc el-icon-question"></i></el-tooltip>
							<el-input v-model="formItemList[index]['mapped_to']" placeholder="请输入映射到新json的哪个字段里"></el-input>
						</uni-forms-item>
						<!-- 移除 -->
						<el-button v-if="index != 0" class="add_btn" type="danger" icon="el-icon-minus" circle @tap="removeFormItem(index)"></el-button>
						<!-- 增加 -->
						<el-button class="add_btn" type="success" icon="el-icon-plus" circle @tap="formItemList.push({})"></el-button>
					</view>

					<!-- <vue-json-editor class="editore" v-model="dataJson" :mode="'code'" lang="zh"></vue-json-editor> -->
					<codemirror v-model="dataJson" :options="optionConfig"></codemirror>
				</el-card>
			</uni-forms>
		</open-alert>
	</view>
</template>

<script>
// import vueJsonEditor from 'vue-json-editor';
import { codemirror } from 'vue-codemirror';
import 'codemirror/lib/codemirror.css';
// 引入主题,配置后生效
import 'codemirror/theme/zenburn.css';
//引入语言,配置后生效
import 'codemirror/mode/htmlmixed/htmlmixed.js';
export default {
	components: {
		// vueJsonEditor,
		codemirror
	},
	data() {
		return {
			requiestForm: {
				url: 'https://ssr.vuejs.org/zh/guide/universal.html',
				request_data: '',
				request_methce: 'GET'
			},
			jsonStr: {
				word: '123'
			}, //请求参数
			requistList: ['GET', 'POST'], //请求方式列表
			dataJson: {}, //返回数据  生成json
			oldDataJson: {}, //生成前的json
			isGenerate: false, //是否生成了数据
			generateBtn: '生成', //生成按钮  生成or还原
			formItemList: [{ required: true }], //映射设置表单
			options: [
				// {
				// 	value: 'zhinan',
				// 	label: '指南',
				// 	children: [
				// 		{
				// 			value: 'shejiyuanze',
				// 			label: '设计原则',
				// 			children: [
				// 				{
				// 					value: 'yizhi',
				// 					label: '一致'
				// 				},
				// 				{
				// 					value: 'fankui',
				// 					label: '反馈'
				// 				},
				// 				{
				// 					value: 'xiaolv',
				// 					label: '效率'
				// 				},
				// 				{
				// 					value: 'kekong',
				// 					label: '可控'
				// 				}
				// 			]
				// 		},
				// 	]
				// },
			],
			// 默认配置
			optionConfig: {
				tabSize: 8, // 缩进格式
				theme: 'zenburn', // 指定主题，对应主题库 JS 需要提前引入
				lineNumbers: true, // 是否显示行号
				//指定语言类型,如果需要编辑和显示其他语言,需要import语言js然后修改此配置
				mode: 'html',
				line: true,
				styleActiveLine: true, // 高亮选中行
				//是否为只读,如果为"nocursor" 不仅仅为只读 连光标都无法在区域聚焦
				readOnly: true,
				hintOptions: {
					completeSingle: true // 当匹配只有一项的时候是否自动补全
				}
			}
		};
	},
	computed: {
		// 是否可以生成
		isCangender() {
			const data = this.formItemList;
			return !(data[0].mapping_field && data[0].mapped_to);
		}
	},
	methods: {
		/**
		 * 触发表单提交
		 */
		async submit(e) {
			// uni.showLoading({
			// 	mask: true
			// });
			this.requiestForm.request_data = this.jsonStr;
			const res = await this.$http(this.requiestForm.url, this.requiestForm.request_data);
			this.dataJson = res;

			/**
			 * 使用递归生成下拉选择值
			 */
			let option = [];
			const getKeys = (obj, father) => {
				if (typeof obj != 'object') return; //这里需要限制一下进来的只能是object类型
				for (const key in obj) {
					// console.log('key===>', key);
					const val = obj[key];
					// 需要判断它的值是否为null
					// 判断它的类型，如果是object则说明其可能拥有子级
					if (val && typeof val == 'object') {
						const type = val.length ? 'array' : 'object';
						const curentVal = {
							label: key + '  ---' + type,
							value: key,
							type: type,
							children: []
						};
						father ? father.push(curentVal) : option.push(curentVal);
						// 进入这里说明该属性可能有子级，这时我们需要进行递归直到没有为止
						// 注意一点：如果值为数组对象时我们只需取其第一项即可
						// 通过length即可判断是object or  array
						getKeys(val.length ? val[0] : val, curentVal.children);
					} else {
						const type = obj[key] != null ? typeof obj[key] : null;
						father
							? father.push({
									label: key + '---' + type,
									value: key,
									type: type
							  })
							: option.push({
									label: key + '---' + type,
									value: key,
									type: type
							  });
					}
				}
			};
			getKeys(res);
			option.forEach((item, index) => {
				if (item.type == 'array') {
					this.options.push(item);
				}
			});
			this.$refs.openAlert.Show();
		},
		// 移除表单一项
		removeFormItem(index) {
			this.formItemList.splice(index, 1);
		},
		// 生成json
		gengderJson() {
			if (this.generateBtn == '生成') {
				this.generateBtn = '还原';
				this.isGenerate = true;
				this.oldDataJson = { ...this.dataJson };
				let resArr = [];
				// 遍历相应的list数据
				this.dataJson[this.formItemList[0]['mapping_field'][0]].forEach(item => {
					let mappedToJson = {};
					for (let item2 of this.formItemList) {
						if (!item2.mapping_field || !item2.mapped_to) continue;
						// 获取要映射的字段
						let str = '';
						let mapping_field_arr = [...item2['mapping_field']];
						mapping_field_arr.splice(0, 1);
						mapping_field_arr.forEach(item3 => {
							str += '.' + item3;
						});
						str = str.substring(1);
						// 获取要映射的值
						const mappingVal = this.$utils.getObjValue(str, item);
						// 设置映射到的结构
						let fatherJson;
						const mappedTo = item2['mapped_to'].split('.');
						// 开始处理
						mappedTo.forEach((item4, index) => {
							// 如果有fatherJson那么就将其子级的值设置为{}以便子级操作，否则就是首级
							fatherJson ? (fatherJson[item4] = {}) : (mappedToJson[item4] = {});
							if (fatherJson && index >= mappedTo.length - 1) {
								// 对象的 最后一个属性，可以设置自己想要的值
								fatherJson[item4] = mappingVal;
							} else if (mappedTo.length == 1) {
								mappedToJson[item4] = mappingVal;
							}
							// 将fatherJson设置为当前所在的json环境
							fatherJson = fatherJson ? fatherJson[item4] : mappedToJson[item4];
						});
					}
					resArr.push(mappedToJson);
				});
				uni.showToast({
					title: '生成成功！共' + resArr.length + '条数据',
					icon: 'none',
					duration: 2000
				});
				this.dataJson = resArr;
			} else {
				// 还原JSON
				this.generateBtn = '生成';
				this.dataJson = { ...this.oldDataJson };
			}
		},
		copyJson() {
			uni.setClipboardData({
				data: JSON.stringify(this.dataJson),
				success: () => {
					this.$message({
						showClose: true,
						message: '数据复制成功!',
						type: 'success',
						center: true
					});
				}
			});
		}
	}
};
</script>

<style lang="less" scoped>
.html-gender {
	.clearfix {
		display: flex;
		align-items: center;
		justify-content: space-between;
		.down_btn {
			color: white;
			text-decoration: none;
			padding: 10rpx 20rpx;
		}
	}

	.box-card {
		width: 600rpx;
	}
	@media screen and (min-width: 800px) {
		.box-card {
			width: 780px;
		}
	}
	.editore {
		/deep/ .jsoneditor-vue {
			height: 800rpx;
		}
	}
	.img_sty {
		width: 200rpx;
		height: 200rpx;
		border-radius: 10rpx;
	}
	.el-tag {
		margin-right: 20rpx;
	}
	.el-tag + .el-tag {
		margin-bottom: 20rpx;
		margin-right: 20rpx;
	}
	.button-new-tag {
		margin-right: 20rpx;
		height: 32px;
		line-height: 30px;
		padding-top: 0;
		padding-bottom: 0;
	}
	.input-new-tag {
		width: 90px;
		vertical-align: bottom;
	}
	.cell_one {
		display: flex;
		justify-content: space-around;
		/deep/ .uni-forms-item__content {
			display: flex;
			align-items: center;
		}
		/deep/ .uni-forms-item__label {
			width: auto !important;
		}
		.info_desc {
			margin-right: 20rpx;
		}
		.add_btn {
			width: 50rpx;
			height: 50rpx;
			padding: 10rpx;
			margin-top: 15rpx;
		}
	}
}
</style>
